<!DOCTYPE html>
<html lang="en">
<head><meta name="generator" content="Hexo 3.9.0">
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="google-site-verification" content="xBT4GhYoi5qRD5tr338pgPM5OWHHIDR6mNg1a3euekI">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <meta name="description" content="GeekZhang的博客">
    <meta name="keyword" content="GeekZhang">
    <link rel="shortcut icon" href="/img/favicon.ico">

    <title>
        
        Ribbon负载均衡以及自定义负载均衡策略 - GeekZhang的博客 | GeekZhang&#39;s Blog
        
    </title>

    <!-- Custom CSS -->
    <link rel="stylesheet" href="/css/aircloud.css">
    <link rel="stylesheet" href="/css/gitment.css">
    <!--<link rel="stylesheet" href="https://imsun.github.io/gitment/style/default.css">-->
    <link href="//at.alicdn.com/t/font_620856_pl6z7sid89qkt9.css" rel="stylesheet" type="text/css">
    <!-- ga & ba script hoook -->
    <script></script>
</head>

<body>

<div class="site-nav-toggle" id="site-nav-toggle">
    <button>
        <span class="btn-bar"></span>
        <span class="btn-bar"></span>
        <span class="btn-bar"></span>
    </button>
</div>

<div class="index-about">
    <i> 不乱于心，不困于情。不畏将来，不念过往。如此，安好。 </i>
</div>

<div class="index-container">
    
    <div class="index-left">
        
<div class="nav" id="nav">
    <div class="avatar-name">
        <div class="avatar ">
            <img src="/img/avatar.jpg" />
        </div>
        <div class="name">
            <i>GeekZhang</i>
        </div>
    </div>
    <div class="contents" id="nav-content">
        <ul>
            <li >
                <a href="/">
                    <i class="iconfont icon-shouye1"></i>
                    <span>主页</span>
                </a>
            </li>
            <li >
                <a href="/tags">
                    <i class="iconfont icon-biaoqian1"></i>
                    <span>标签</span>
                </a>
            </li>
            <li >
                <a href="/archive">
                    <i class="iconfont icon-guidang2"></i>
                    <span>存档</span>
                </a>
            </li>
            <li >
                <a href="/about/">
                    <i class="iconfont icon-guanyu2"></i>
                    <span>关于</span>
                </a>
            </li>
            
            <li>
                <a id="search">
                    <i class="iconfont icon-sousuo1"></i>
                    <span>搜索</span>
                </a>
            </li>
            
        </ul>
    </div>
    
        <div id="toc" class="toc-article">
    
</div>
    
</div>


<div class="search-field" id="search-field">
    <div class="search-container">
        <div class="search-input">
            <span id="esc-search"> <i class="icon-fanhui iconfont"></i></span>
            <input id="search-input"/>
            <span id="begin-search">搜索</span>
        </div>
        <div class="search-result-container" id="search-result-container">

        </div>
    </div>
</div>

        <div class="index-about-mobile">
            <i> 不乱于心，不困于情。不畏将来，不念过往。如此，安好。 </i>
        </div>
    </div>
    
    <div class="index-middle">
        <!-- Main Content -->
        


<div class="post-container">
    <div class="post-title">
        Ribbon负载均衡以及自定义负载均衡策略
    </div>

    <div class="post-meta">
        <span class="attr">发布于：<span>2019-04-03 23:30:54</span></span>
        
        <span class="attr">标签：/
        
        <a class="tag" href="/tags/#java" title="java">java</a>
        <span>/</span>
        
        <a class="tag" href="/tags/#springcloud" title="springcloud">springcloud</a>
        <span>/</span>
        
        <a class="tag" href="/tags/#ribbon" title="ribbon">ribbon</a>
        <span>/</span>
        
        
        </span>
        <span class="attr">访问：<span id="busuanzi_value_page_pv"></span>
</span>
</span>
    </div>
    <div class="post-content no-indent">
        <p>首先看下Ribbon自带的负载均衡策略：</p>
<table>
<thead>
<tr>
<th>策略名</th>
<th>策略声明</th>
<th>策略描述</th>
<th>实现说明</th>
</tr>
</thead>
<tbody>
<tr>
<td>BestAvailableRule</td>
<td>public class BestAvailableRule extends ClientConfigEnabledRoundRobinRule</td>
<td>选择一个最小的并发请求的server</td>
<td>逐个考察Server，如果Server被tripped了，则忽略，在选择其中ActiveRequestsCount最小的server</td>
</tr>
<tr>
<td>AvailabilityFilteringRule</td>
<td>public class AvailabilityFilteringRule extends PredicateBasedRule</td>
<td>过滤掉那些因为一直连接失败的被标记为circuit tripped的后端server，并过滤掉那些高并发的的后端server（active connections 超过配置的阈值）</td>
<td>使用一个AvailabilityPredicate来包含过滤server的逻辑，其实就就是检查status里记录的各个server的运行状态</td>
</tr>
<tr>
<td>WeightedResponseTimeRule</td>
<td>public class WeightedResponseTimeRule extends RoundRobinRule</td>
<td>根据相应时间分配一个weight，相应时间越长，weight越小，被选中的可能性越低。</td>
<td>一个后台线程定期的从status里面读取评价响应时间，为每个server计算一个weight。Weight的计算也比较简单responsetime 减去每个server自己平均的responsetime是server的权重。当刚开始运行，没有形成statas时，使用roubine策略选择server。</td>
</tr>
<tr>
<td>RetryRule</td>
<td>public class RetryRule extends AbstractLoadBalancerRule</td>
<td>对选定的负载均衡策略机上重试机制。</td>
<td>在一个配置时间段内当选择server不成功，则一直尝试使用subRule的方式选择一个可用的server</td>
</tr>
<tr>
<td>RoundRobinRule</td>
<td>public class RoundRobinRule extends AbstractLoadBalancerRule</td>
<td>roundRobin方式轮询选择server</td>
<td>轮询index，选择index对应位置的server</td>
</tr>
<tr>
<td>RandomRule</td>
<td>public class RandomRule extends AbstractLoadBalancerRule</td>
<td>随机选择一个server</td>
<td>在index上随机，选择index对应位置的server</td>
</tr>
<tr>
<td>ZoneAvoidanceRule</td>
<td>public class ZoneAvoidanceRule extends PredicateBasedRule</td>
<td>复合判断server所在区域的性能和server的可用性选择server</td>
<td>使用ZoneAvoidancePredicate和AvailabilityPredicate来判断是否选择某个server，前一个判断判定一个zone的运行性能是否可用，剔除不可用的zone（的所有server），AvailabilityPredicate用于过滤掉连接数过多的Server。</td>
</tr>
</tbody>
</table>
<blockquote>
<p>以上表格来源：<a href="http://ju.outofmemory.cn/entry/253843" target="_blank" rel="noopener">http://ju.outofmemory.cn/entry/253843</a></p>
</blockquote>
<p>除此之外，新版的Ribbon还有一些其他自带策略。</p>
<p>首先添加Ribbon依赖：<em>（如果使用Feign，则自带了Ribbon包）</em><br><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.springframework.cloud<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>spring-cloud-starter-ribbon<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br></pre></td></tr></table></figure></p>
<p>创建配置类：<br><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Configuration</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">RibbonConfiguration</span> </span>&#123;</span><br><span class="line">    <span class="meta">@Bean</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> IRule <span class="title">ribbonRule</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">new</span> RoundRobinRule();  <span class="comment">//这里采用轮询策略</span></span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></p>
<p>配置启用类：<br><figure class="highlight less"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="variable">@Configuration</span></span><br><span class="line"><span class="variable">@RibbonClient</span>(name = <span class="string">"server1"</span>, configuration = RibbonConfiguration.class)</span><br><span class="line">public class TestConfiguration &#123;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></p>
<p>这里name参数为需要负载均衡的服务名，configuration参数指定配置类，这种通过java类配置较为复杂，后面<br>会介绍通过yml配置文件配置以及对所有服务配置负载均衡的方法。</p>
<p>到此完成负载均衡的配置，我这里调用的服务server1，如果你已经在eureka注册中心注册了两个application.name都为<br>server1的服务，调用时Ribbon会轮询去掉用。</p>
<p>此外，我们还可以自定义自己的负载均衡策略，此处给一个例子：</p>
<figure class="highlight axapta"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">MyTestRule</span> <span class="keyword">extends</span> <span class="title">AbstractLoadBalancerRule</span> </span>&#123;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">int</span> total = <span class="number">0</span>;            <span class="comment">// 总共被调用的次数</span></span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">int</span> currentIndex = <span class="number">0</span>;    <span class="comment">// 当前提供服务索引</span></span><br><span class="line">    <span class="keyword">public</span> Server choose(ILoadBalancer lb, Object key) &#123;</span><br><span class="line">        <span class="keyword">if</span> (lb == <span class="keyword">null</span>) &#123;</span><br><span class="line">            <span class="keyword">return</span> <span class="keyword">null</span>;</span><br><span class="line">        &#125;</span><br><span class="line">        Server <span class="keyword">server</span> = <span class="keyword">null</span>;</span><br><span class="line">        <span class="keyword">while</span> (<span class="keyword">server</span> == <span class="keyword">null</span>) &#123;</span><br><span class="line">            <span class="keyword">if</span> (Thread.interrupted()) &#123;</span><br><span class="line">                <span class="keyword">return</span> <span class="keyword">null</span>;</span><br><span class="line">            &#125;</span><br><span class="line">            List&lt;Server&gt; upList = lb.getReachableServers();</span><br><span class="line">            List&lt;Server&gt; allList = lb.getAllServers();</span><br><span class="line">            <span class="keyword">int</span> serverCount = allList.size();</span><br><span class="line">            <span class="keyword">if</span> (serverCount == <span class="number">0</span>) &#123;</span><br><span class="line">                <span class="keyword">return</span> <span class="keyword">null</span>;</span><br><span class="line">            &#125;</span><br><span class="line"></span><br><span class="line">            <span class="keyword">if</span> (total &lt; <span class="number">3</span>) &#123;</span><br><span class="line">                <span class="keyword">server</span> = upList.get(currentIndex);</span><br><span class="line">                total++;</span><br><span class="line">            &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">                total = <span class="number">0</span>;</span><br><span class="line">                currentIndex++;</span><br><span class="line">                <span class="keyword">if</span> (currentIndex &gt;= upList.size()) &#123;</span><br><span class="line">                    currentIndex = <span class="number">0</span>;</span><br><span class="line">                &#125;</span><br><span class="line">            &#125;</span><br><span class="line">            <span class="keyword">if</span> (<span class="keyword">server</span> == <span class="keyword">null</span>) &#123;</span><br><span class="line">                Thread.yield();</span><br><span class="line">                <span class="keyword">continue</span>;</span><br><span class="line">            &#125;</span><br><span class="line">            <span class="keyword">if</span> (<span class="keyword">server</span>.isAlive()) &#123;</span><br><span class="line">                <span class="keyword">return</span> (<span class="keyword">server</span>);</span><br><span class="line">            &#125;</span><br><span class="line">            <span class="keyword">server</span> = <span class="keyword">null</span>;</span><br><span class="line">            Thread.yield();</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">server</span>;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    @Override</span><br><span class="line">    <span class="keyword">public</span> Server choose(Object key) &#123;</span><br><span class="line">        <span class="keyword">return</span> choose(getLoadBalancer(), key);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    @Override</span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> initWithNiwsConfig(IClientConfig iClientConfig) &#123;</span><br><span class="line"></span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>大致意思为每调用服务A三次便会调用相同的服务A2,三次后调用A3一次类推，调用到最大服务次数索引置为0<br>再如此循环。将上述配置类的 return new RoundRobinRule(); 改为本类<br>  return MyTestRule 即可实现。</p>
<p>由于java配置类配置较为繁琐，以下给出application.yml配置方法：<br><figure class="highlight css"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="selector-tag">server1</span>:</span><br><span class="line">  <span class="selector-tag">ribbon</span>:</span><br><span class="line">    <span class="selector-tag">NFLoadBalancerRuleClassName</span>: <span class="selector-tag">com</span><span class="selector-class">.netflix</span><span class="selector-class">.loadbalancer</span><span class="selector-class">.RandomRule</span> #配置规则 随机</span><br><span class="line">#    <span class="selector-tag">NFLoadBalancerRuleClassName</span>: <span class="selector-tag">com</span><span class="selector-class">.netflix</span><span class="selector-class">.loadbalancer</span><span class="selector-class">.RoundRobinRule</span> #配置规则 轮询</span><br><span class="line">#    <span class="selector-tag">NFLoadBalancerRuleClassName</span>: <span class="selector-tag">com</span><span class="selector-class">.netflix</span><span class="selector-class">.loadbalancer</span><span class="selector-class">.RetryRule</span> #配置规则 重试</span><br><span class="line">#    <span class="selector-tag">NFLoadBalancerRuleClassName</span>: <span class="selector-tag">com</span><span class="selector-class">.netflix</span><span class="selector-class">.loadbalancer</span><span class="selector-class">.WeightedResponseTimeRule</span> #配置规则 响应时间权重</span><br><span class="line">#    <span class="selector-tag">NFLoadBalancerRuleClassName</span>: <span class="selector-tag">com</span><span class="selector-class">.geekzhang</span><span class="selector-class">.server4</span><span class="selector-class">.configuration</span><span class="selector-class">.MyTestRule</span> #自定义规则，包路径自行修改</span><br></pre></td></tr></table></figure></p>
<p>此处server1为sercer1服务的负载均衡策略，如果需要全局的负载均衡策略，只需将前缀删掉即可，如下：</p>
<figure class="highlight css"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="selector-tag">ribbon</span>:</span><br><span class="line">  <span class="selector-tag">NFLoadBalancerRuleClassName</span>: <span class="selector-tag">com</span><span class="selector-class">.netflix</span><span class="selector-class">.loadbalancer</span><span class="selector-class">.RandomRule</span> #配置规则 随机</span><br><span class="line">#  <span class="selector-tag">NFLoadBalancerRuleClassName</span>: <span class="selector-tag">com</span><span class="selector-class">.netflix</span><span class="selector-class">.loadbalancer</span><span class="selector-class">.RoundRobinRule</span> #配置规则 轮询</span><br><span class="line">#  <span class="selector-tag">NFLoadBalancerRuleClassName</span>: <span class="selector-tag">com</span><span class="selector-class">.netflix</span><span class="selector-class">.loadbalancer</span><span class="selector-class">.RetryRule</span> #配置规则 重试</span><br><span class="line">#  <span class="selector-tag">NFLoadBalancerRuleClassName</span>: <span class="selector-tag">com</span><span class="selector-class">.netflix</span><span class="selector-class">.loadbalancer</span><span class="selector-class">.WeightedResponseTimeRule</span> #配置规则 响应时间权重</span><br><span class="line">#  <span class="selector-tag">NFLoadBalancerRuleClassName</span>: <span class="selector-tag">com</span><span class="selector-class">.geekzhang</span><span class="selector-class">.server4</span><span class="selector-class">.configuration</span><span class="selector-class">.MyTestRule</span> #自定义规则，包路径自行修改</span><br></pre></td></tr></table></figure>

        
        <br />
        <div id="comment-container">
        </div>
        <div id="disqus_thread"></div>

        <div id="lv-container">
        </div>

    </div>
</div>

    </div>
</div>


<footer class="footer">
    <ul class="list-inline text-center">
        
        

        

        

        
        <li>
            <a target="_blank"  href="https://github.com/geekzhi">
                            <span class="fa-stack fa-lg">
                                <i class="iconfont icon-github"></i>
                            </span>
            </a>
        </li>
        

        

    </ul>
    
    <p>
        <span id="busuanzi_container_site_pv">
            <span id="busuanzi_value_site_pv"></span>PV
        </span>
        <span id="busuanzi_container_site_uv">
            <span id="busuanzi_value_site_uv"></span>UV
        </span>
        Created By <a href="https://hexo.io/">Hexo</a>  Theme <a href="https://github.com/aircloud/hexo-theme-aircloud">AirCloud</a></p>
</footer>




</body>

<script>
    // We expose some of the variables needed by the front end
    window.hexo_search_path = "search.json"
    window.hexo_root = "/"
    window.isPost = true
</script>
<script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.min.js"></script>
<script src="/js/index.js"></script>
<script async src="//busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js"></script>




</html>
